<template>
  <el-upload
    class="uploadBase"
    v-model:file-list="fileList"
    action="#"
    :multiple="limit != 1"
    :auto-upload="false"
    :show-file-list="false"
    :on-change="handleChange"
    :accept="accept"
    v-bind="attrs"
  >
    <slot>
      <el-button :disabled="disabled" :type="buttonType">{{ buttonText }}</el-button>
    </slot>

    <!-- 提示说明文字  -->
    <template #tip>
      <slot name="tip"></slot>
    </template>
    <!-- 缩略图模板的内容 -->
    <template #file="{ file }">
      <slot name="file" :file="file"></slot>
    </template>
  </el-upload>

  <!-- upload bottom -->
  <slot name="uploadBottom"></slot>
</template>

<script setup>
import { ElMessage } from 'element-plus';

const attrs = useAttrs();

const props = defineProps({
  modelValue: {
    type: Array,
    default: [],
  },
  buttonText: {
    // 按钮文本
    type: String,
    default: 'Upload',
  },
  maxSize: {
    // 单个最大上传尺寸, 单位是M, 0为不限制
    type: Number,
    default: 0,
  },
  maxAllSize: {
    // 多个合计上传最大尺寸, 单位是M, 0为不限制
    type: Number,
    default: 0,
  },
  limit: {
    // 最大上传数量, 0为不限制
    type: Number,
    default: 0,
  },
  isRaw: {
    // 获取的file文件，还是file.row数据
    type: Boolean,
    default: true,
  },
  accept: {
    /**
     * 上传文件类型
     * xlsx: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
     * pdf: .pdf
     * docx: application/vnd.openxmlformats-officedocument.wordprocessingml.document
     * doc: application/msword
     * zip: aplication/zip
     * image: image/*(所有图片格式)，限定格式如： .png,.jpg,.jpeg.....
     * .....
     */
    type: String,
    default: '',
  },
  acceptNotice: {
    // 上传格式不符提示
    type: String,
    default: 'This transfer format is not supported',
  },
  buttonType: {
    type: String,
    default: '',
  },
  disabled: {
    // 是否禁用
    type: Boolean,
    default: false,
  },
});
const emits = defineEmits(['update:modelValue']);

let fileList = ref([]);
let totalSize = ref(0);

onMounted(() => {
  init(props.modelValue);
});

// 初始file 数据
function init(file) {
  fileList.value = file;
  totalSize.value = 0;
}

// upload change事件
function handleChange(file) {
  const maxSize = props.maxSize * 1024 * 1024;
  const maxAllSize = props.maxAllSize * 1024 * 1024;
  const { raw } = file;
  let flag = true;
  ElMessage.closeAll();
  // 附件为空，不能上传
  if (raw.size === 0) {
    ElMessage.warning(`File is empty`);
    flag = false;
  }

  if (maxSize && raw.size > maxSize) {
    // 单个不能超过最大尺寸
    ElMessage.warning(`No more than ${props.maxSize}MB`);
    flag = false;
  } else if (maxAllSize && totalSize.value + raw.size > maxAllSize) {
    // 多个总和不能超过最大尺寸
    ElMessage.warning(`Amount No more than ${props.maxAllSize}MB`);
    flag = false;
  } else if (props.accept) {
    // 文件类型校验
    let fileSuffix = raw?.name?.substring(raw.name.lastIndexOf('.'));
    fileSuffix = fileSuffix?.toLowerCase(); // 转小写匹配
    if (props.accept.indexOf(fileSuffix) === -1) {
      ElMessage.warning(props.acceptNotice);
      flag = false;
    }
  }
  if (flag) {
    totalSize.value += raw.size;
    let len = fileList.value?.length;
    if (props.limit && props.limit <= len) fileList.value.splice(0, len + 1 - props.limit);
    raw.date = new Date();
    file.raw.date = new Date();
    fileList.value = [...(fileList.value ?? []), props.isRaw ? raw : file];
    emits('update:modelValue', fileList.value);
  } else {
    // 在文件列中取出失败的文件
    if (!fileList.value?.length) return;
    fileList.value.forEach((item, i) => {
      if (item.uid === file.uid) fileList.value.splice(i, 1);
    });
  }
}

defineExpose({
  init,
});
</script>
<style lang="scss" scoped>
.uploadBase :deep(.el-upload-dragger) {
  border: none;
  width: fit-content;
  padding: 0;
}
.uploadBase :deep(.el-upload--text) {
  width: fit-content;
}
</style>
